package com.github.abel533;

import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ShowAll {
    public static void main(String[] args) throws IOException {
//        print("org/springframework", upperCaseName(name -> name.endsWith("UTILS.CLASS") || name.endsWith("UTIL.CLASS")));
//        System.out.println("\n\n\n\n\n\n");

//        print("org/springframework", upperCaseName(name -> name.endsWith("AWARE.CLASS")).and(useClass(c -> c.isInterface())));
//        System.out.println("\n\n\n\n\n\n");

//        print("org/springframework", upperCaseName(name -> name.endsWith("BEAN.CLASS")).and(useClass(c -> c.isInterface())));
//        System.out.println("\n\n\n\n\n\n");
//
//        print("org/springframework", upperCaseName(name -> name.endsWith("PROCESSOR.CLASS")).and(useClass(c -> c.isInterface())));
//        System.out.println("\n\n\n\n\n\n");
//
//        print("org/springframework", upperCaseName(name -> name.endsWith("LISTENER.CLASS")).and(useClass(c -> c.isInterface())));
//        System.out.println("\n\n\n\n\n\n");
//
        print("org/springframework", upperCaseName(name -> name.endsWith("INITIALIZER.CLASS")).and(useClass(c -> c.isInterface())));

    }

    public static Predicate<JarEntry> upperCaseName(Predicate<String> predicate){
        return entry -> {
            String name = entry.getName().toUpperCase();
            return predicate.test(name);
        };
    }

    public static Predicate<JarEntry> useClass(Predicate<Class> predicate){
        return entry -> {
            String className = entry.getName().substring(0, entry.getName().indexOf(".class")).replaceAll("/", ".");
            Class<?> clazz;
            try {
                clazz = Class.forName(className);
            } catch (Throwable e) {
                return false;
            }
            return predicate.test(clazz);
        };
    }

    public static void print(String path, Predicate<JarEntry> predicate) throws IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Enumeration<URL> resources = classLoader.getResources(path);
        int index = 1;
        while (resources.hasMoreElements()) {
            URL url = resources.nextElement();
            if ("jar".equals(url.getProtocol())) {
                JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile();
                Enumeration<JarEntry> entries = jar.entries();
                boolean showPath = false;
                while (entries.hasMoreElements()) {
                    JarEntry entry = entries.nextElement();
                    if (predicate.test(entry)) {
                        if(!showPath){
                            showPath = true;
                            System.out.println("======================================");
                            System.out.println(url.getPath().substring(0, url.getPath().indexOf("!")));
                        }
                        System.out.printf("%4d : %s\n", index++, entry.getName());
                    }
                }
            }
        }
    }
}
